// #include<unistd.h>
// #include<iostream>
// using namespace std;

// #define N 2

// //child
// void Writer(int wfd)
// {

// }

// //father
// void Reader(int rfd)
// {

// }



// int main()
// {
//     int pipefd[N] = { 0 };
//     int n = pipe(pipefd);
//     if (n < 0) return 1;  //创建失败

//     //创建子进程
//     pid_t id = fork();
//     if (id < 0) return 2;//创建子进程失败
//     else if (id == 0) //child
//     {  
//         //子进程写， 父进程读。 所以要关闭子进程的读入端， 关闭父进程的写入段。
//         close(pipefd[0]);
        



//         close(pipefd[1]);
//     }
    
//     //父进程关闭写入端
//     close(pipefd[1]);                           

//     return 0;
// } 






// #include<unistd.h>
// #include<iostream>
// using namespace std;

// #define N 2

// //child
// void Writer(int wfd)
// {

// }

// //father
// void Reader(int rfd)
// {

// }



// int main()
// {
//     int pipefd[N] = { 0 };
//     int n = pipe(pipefd);
//     if (n < 0) return 1;  //创建失败

//     // cout << "pipefd[0]:" << pipefd[0] << " " << ", pipefd[1]:" << pipefd[1] << endl;

//     //child->w, father->r;
//     pid_t id = fork();
//     if (id < 0) return 2;//创建子进程失败
//     else if (id == 0) //child
//     {  
//         //子进程写， 父进程读。 所以要关闭子进程的读入端， 关闭父进程的写入段。
//         close(pipefd[0]);

//         //IPCcode
//         Writer(pipdfd[1]);



//         close(pipefd[1]);
//     }
    
//     //父进程关闭写入端
//     close(pipefd[1]);                           
//     Reader(pipefd[0]);

//     return 0;
// } 

// #include<unistd.h>
// #include<iostream>
// #include<cstdio>
// #include<cstdlib>
// #include<sys/types.h>
// #include<sys/wait.h>
// #include<cstring>


// using namespace std;
// #include<string> 


// #define N 2
// #define NUM 1024   //缓冲区最大大小

// //child
// void Writer(int wfd)
// {
//     string s = "hello, I am  child";
//     pid_t self = getpid();  //获取自己的进程编号。 
//     //写一些信息的时候， 带上编号
//     int number = 0;
    
//     //先定义缓冲区
//     char buffer[NUM]; 
//     while (true)
//     {

//         //构建发送字符串
//         buffer[0] = 0; //字符串清空， 可以用来提醒阅读代码的人，这个是一个字符串
//         //
//         snprintf(buffer, sizeof(buffer), "%s-%d-%d", s.c_str(), self, number++);
//         //cout << buffer << endl; //测试


//         //发送/写入给父进程
//         write(wfd, buffer, strlen(buffer));   //这用不用加1， 不需要。  因为这里是管道文件。 是打印的内容。 不需要分隔符！



//         sleep(1);
//     } 

// }

// //father
// void Reader(int rfd)
// {

// }



// int main()
// {
//     int pipefd[N] = { 0 };
//     int n = pipe(pipefd);
//     if (n < 0) return 1;  //创建失败

//     // cout << "pipefd[0]:" << pipefd[0] << " " << ", pipefd[1]:" << pipefd[1] << endl;

//     //child->w, father->r;
//     pid_t id = fork();
//     if (id < 0) return 2;//创建子进程失败
//     else if (id == 0) //child
//     {  
//         //子进程写， 父进程读。 所以要关闭子进程的读入端， 关闭父进程的写入段。
//         close(pipefd[0]);

//         //IPCcode
//         Writer(pipefd[1]);

//         close(pipefd[1]);
//     }
    


//     //父进程关闭写入端
//     close(pipefd[1]);                           
//     Reader(pipefd[0]);

//     //父进程要等待子进程
//     pid_t rid = waitpid(id, nullptr, 0); //父进程读取数据后，要等待子进程， 这里的退出码并不关心。 
//     if (rid < 0) return 3;

//     close(pipefd[0]);

//     return 0;
// } 



// #include<unistd.h>
// #include<iostream>
// #include<cstdio>
// #include<cstdlib>
// #include<sys/types.h>
// #include<sys/wait.h>
// #include<cstring>


// using namespace std;
// #include<string> 


// #define N 2
// #define NUM 1024   //缓冲区最大大小

// //child
// void Writer(int wfd)
// {
//     string s = "hello, I am  child";
//     pid_t self = getpid();  //获取自己的进程编号。 
//     //写一些信息的时候， 带上编号
//     int number = 0;
    
//     //先定义缓冲区
//     char buffer[NUM]; 
//     while (true)
//     {
//         //构建发送字符串
//         buffer[0] = 0; //字符串清空， 可以用来提醒阅读代码的人，这个是一个字符串
//         //
//         snprintf(buffer, sizeof(buffer), "%s-%d-%d", s.c_str(), self, number++);
//         //cout << buffer << endl; //测试

//         //发送/写入给父进程
//         write(wfd, buffer, strlen(buffer));   //这用不用加1， 不需要。  因为这里是管道文件。 是打印的内容。 不需要分隔符！
//         cout << number << endl;
//     } 

// }

// // //father
// void Reader(int rfd)
// {
//     //创建buffer
//     char buffer[NUM]; //NUM上面定义的是1024
    
//     while (true)
//     {
//         sleep(5);

//         buffer[0] = 0; //告诉全世界， 这是个字符串
//         ssize_t n = read(rfd, buffer, sizeof(buffer)); //sizeof !=  strlen, 这里不能strlen(buffer), 因为buffer里面没有\0.
//         if(n > 0) //说明读取成功
//         {
//             buffer[n] = 0; //在最后一个字符的后面添加一个\0。   
//         }

//         cout << "father: " << getpid() << ":" << buffer << endl;
//     }

//  }


// int main()
// {
//     int pipefd[N] = { 0 };
//     int n = pipe(pipefd);
//     if (n < 0) return 1;  //创建失败

//     // cout << "pipefd[0]:" << pipefd[0] << " " << ", pipefd[1]:" << pipefd[1] << endl;

//     //child->w, father->r;
//     pid_t id = fork();
//     if (id < 0) return 2;//创建子进程失败
//     else if (id == 0) //child
//     {  
//         //子进程写， 父进程读。 所以要关闭子进程的读入端， 关闭父进程的写入段。
//         close(pipefd[0]);

//         //IPCcode
//         Writer(pipefd[1]);

//         close(pipefd[1]);
//     }

//     //父进程关闭写入端
//     close(pipefd[1]);                           
//     Reader(pipefd[0]);                     

//     //父进程要等待子进程
//     pid_t rid = waitpid(id, nullptr, 0); //父进程读取数据后，要等待子进程， 这里的退出码并不关心。 
//     if (rid < 0) return 3;

//     close(pipefd[0]);

//     return 0;
// } 

//情况2

// #include<unistd.h>
// #include<iostream>
// #include<cstdio>
// #include<cstdlib>
// #include<sys/types.h>
// #include<sys/wait.h>
// #include<cstring>


// using namespace std;
// #include<string> 


// #define N 2
// #define NUM 1024   //缓冲区最大大小

// //child
// void Writer(int wfd)
// {
//     string s = "hello, I am  child";
//     pid_t self = getpid();  //获取自己的进程编号。 
//     //写一些信息的时候， 带上编号
//     int number = 0;
    
//     //先定义缓冲区
//     char buffer[NUM]; 
//     while (true)
//     {
//         char c = 'c';
//         write(wfd, &c, 1);   

//         number++; //一次打印一个字符， 打印一个字符， number加一， 然后打印number
//         cout << number << endl;
//     } 
// }

// //father
// void Reader(int rfd)
// {
//     //创建buffer
//     char buffer[NUM];
    
//     while (true)
//     {
//         sleep(50);

//         buffer[0] = 0; //告诉全世界， 这是个字符串
//         ssize_t n = read(rfd, buffer, sizeof(buffer)); //sizeof !=  strlen, 这里不能strlen(buffer), 因为buffer里面没有\0.
//         if(n > 0) //说明读取成功
//         {
//             buffer[n] = 0; //在最后一个字符的后面添加一个\0。   
//         }

//         cout << "father: " << getpid() << ":" << buffer << endl;
//     }
    


// }



// int main()
// {
//     int pipefd[N] = { 0 };
//     int n = pipe(pipefd);
//     if (n < 0) return 1;  //创建失败

//     // cout << "pipefd[0]:" << pipefd[0] << " " << ", pipefd[1]:" << pipefd[1] << endl;

//     //child->w, father->r;
//     pid_t id = fork();
//     if (id < 0) return 2;//创建子进程失败
//     else if (id == 0) //child
//     {  
//         //子进程写， 父进程读。 所以要关闭子进程的读入端， 关闭父进程的写入段。
//         close(pipefd[0]);

//         //IPCcode
//         Writer(pipefd[1]);

//         close(pipefd[1]);
//     }
    


//     //父进程关闭写入端
//     close(pipefd[1]);                           
//     Reader(pipefd[0]);

//     //父进程要等待子进程
//     pid_t rid = waitpid(id, nullptr, 0); //父进程读取数据后，要等待子进程， 这里的退出码并不关心。 
//     if (rid < 0) return 3;

//     close(pipefd[0]);

//     return 0;
// } 

//情况3

// #include<unistd.h>
// #include<iostream>
// #include<cstdio>
// #include<cstdlib>
// #include<sys/types.h>
// #include<sys/wait.h>
// #include<cstring>


// using namespace std;
// #include<string> 


// #define N 2
// #define NUM 1024   //缓冲区最大大小

// //child
// void Writer(int wfd)
// {
//     string s = "hello, I am  child";
//     pid_t self = getpid();  //获取自己的进程编号。 
//     //写一些信息的时候， 带上编号
//     int number = 0;
    
//     //先定义缓冲区
//     char buffer[NUM]; 
//     while (true)
//     {
//         sleep(1);
//         //构建发送字符串
//         // buffer[0] = 0; //字符串清空， 可以用来提醒阅读代码的人，这个是一个字符串
//         // //
//         // snprintf(buffer, sizeof(buffer), "%s-%d-%d", s.c_str(), self, number++);
//         // //cout << buffer << endl; //测试

//         // //发送/写入给父进程
//         char c = 'c';
//         write(wfd, &c, 1);   //这用不用加1， 不需要。  因为这里是管道文件。 是打印的内容。 不需要分隔符！

//         number++;
//         cout << number << endl;
//         if (number > 5) break;

    
//     } 
// }

// //father
// void Reader(int rfd)
// {
//     //创建buffer
//     char buffer[NUM];
    
//     while (true)
//     {

//         buffer[0] = 0; //告诉全世界， 这是个字符串
//         ssize_t n = read(rfd, buffer, sizeof(buffer)); //sizeof !=  strlen, 这里不能strlen(buffer), 因为buffer里面没有\0.
//         if(n > 0) //说明读取成功
//         {
//             buffer[n] = 0; //在最后一个字符的后面添加一个\0。   
//             cout << "father: " << getpid() << ":" << buffer << endl;
//         }
//         cout << "n:" << n << endl;  
//     }
    


// }



// int main()
// {
//     int pipefd[N] = { 0 };
//     int n = pipe(pipefd);
//     if (n < 0) return 1;  //创建失败

//     // cout << "pipefd[0]:" << pipefd[0] << " " << ", pipefd[1]:" << pipefd[1] << endl;

//     //child->w, father->r;
//     pid_t id = fork();
//     if (id < 0) return 2;//创建子进程失败
//     else if (id == 0) //child
//     {  
//         //子进程写， 父进程读。 所以要关闭子进程的读入端， 关闭父进程的写入段。
//         close(pipefd[0]);

//         //IPCcode
//         Writer(pipefd[1]);

//         close(pipefd[1]);
//     }
    


//     //父进程关闭写入端
//     close(pipefd[1]);                           
//     Reader(pipefd[0]);

//     //父进程要等待子进程
//     pid_t rid = waitpid(id, nullptr, 0); //父进程读取数据后，要等待子进程， 这里的退出码并不关心。 
//     if (rid < 0) return 3;

//     close(pipefd[0]);

//     return 0;
// } 


// #include<unistd.h>
// #include<iostream>
// #include<cstdio>
// #include<cstdlib>
// #include<sys/types.h>
// #include<sys/wait.h>
// #include<cstring>


// using namespace std;
// #include<string> 


// #define N 2
// #define NUM 1024   //缓冲区最大大小

// //child
// void Writer(int wfd)
// {
//     string s = "hello, I am  child";
//     pid_t self = getpid();  //获取自己的进程编号。 
//     //写一些信息的时候， 带上编号
//     int number = 0;
    
//     //先定义缓冲区
//     char buffer[NUM]; 
//     while (true)
//     {
//         sleep(1);
//         //构建发送字符串
//         // buffer[0] = 0; //字符串清空， 可以用来提醒阅读代码的人，这个是一个字符串
//         // //
//         // snprintf(buffer, sizeof(buffer), "%s-%d-%d", s.c_str(), self, number++);
//         // //cout << buffer << endl; //测试

//         // //发送/写入给父进程
//         char c = 'c';
//         write(wfd, &c, 1);   //这用不用加1， 不需要。  因为这里是管道文件。 是打印的内容。 不需要分隔符！

//         number++;
//         cout << number << endl;
//         if (number > 5) break;

    
//     } 
// }

// //father
// void Reader(int rfd)
// {
//     //创建buffer
//     char buffer[NUM];
    
//     while (true)
//     {

//         buffer[0] = 0; //告诉全世界， 这是个字符串
//         ssize_t n = read(rfd, buffer, sizeof(buffer)); //sizeof !=  strlen, 这里不能strlen(buffer), 因为buffer里面没有\0.
//         if(n > 0) //说明读取成功
//         {
//             buffer[n] = 0; //在最后一个字符的后面添加一个\0。   
//             cout << "father: " << getpid() << ":" << buffer << endl;
//         }
//         else if (n == 0) break;
//         else break;
        
//     }
    


// }



// int main()
// {
//     int pipefd[N] = { 0 };
//     int n = pipe(pipefd);
//     if (n < 0) return 1;  //创建失败

//     // cout << "pipefd[0]:" << pipefd[0] << " " << ", pipefd[1]:" << pipefd[1] << endl;

//     //child->w, father->r;
//     pid_t id = fork();
//     if (id < 0) return 2;//创建子进程失败
//     else if (id == 0) //child
//     {  
//         //子进程写， 父进程读。 所以要关闭子进程的读入端， 关闭父进程的写入段。
//         close(pipefd[0]);

//         //IPCcode
//         Writer(pipefd[1]);

//         close(pipefd[1]);
//     }
    


//     //父进程关闭写入端
//     close(pipefd[1]);                           
//     Reader(pipefd[0]);

//     //父进程要等待子进程
//     pid_t rid = waitpid(id, nullptr, 0); //父进程读取数据后，要等待子进程， 这里的退出码并不关心。 
//     if (rid < 0) return 3;

//     close(pipefd[0]);

//     return 0;
// } 

// #include<unistd.h>
// #include<iostream>
// #include<cstdio>
// #include<cstdlib>
// #include<sys/types.h>
// #include<sys/wait.h>
// #include<cstring>


// using namespace std;
// #include<string> 


// #define N 2
// #define NUM 1024   //缓冲区最大大小

// //child
// void Writer(int wfd)
// {
//     string s = "hello, I am  child";
//     pid_t self = getpid();  //获取自己的进程编号。 
//     //写一些信息的时候， 带上编号
//     int number = 0;
    
//     //先定义缓冲区
//     char buffer[NUM]; 
//     while (true)
//     {
//         sleep(1);
//         //构建发送字符串
//         buffer[0] = 0; //字符串清空， 可以用来提醒阅读代码的人，这个是一个字符串
//         //
//         snprintf(buffer, sizeof(buffer), "%s-%d-%d", s.c_str(), self, number++);
//         // cout << buffer << endl; //测试
//         write(wfd, buffer, strlen(buffer));

//         // //发送/写入给父进程
//         // char c = 'c';
//         // write(wfd, &c, 1);   //这用不用加1， 不需要。  因为这里是管道文件。 是打印的内容。 不需要分隔符！

//         // number++;
//         // cout << number << endl;
//         // if (number > 5) break;

    
//     } 
// }

// //father
// void Reader(int rfd)
// {
//     //创建buffer
//     char buffer[NUM];
//     int cnt = 0;
//     while (true)
//     {

//         buffer[0] = 0; //告诉全世界， 这是个字符串
//         ssize_t n = read(rfd, buffer, sizeof(buffer)); //sizeof !=  strlen, 这里不能strlen(buffer), 因为buffer里面没有\0.
//         if(n > 0) //说明读取成功
//         {
//             buffer[n] = 0; //在最后一个字符的后面添加一个\0。   
//             cout << "father: " << getpid() << ":" << buffer << endl;
//         }
//         else if (n == 0) break;
//         else break;
        
//         cnt++;
//         if (cnt > 5) break;
//     }

// }



// int main()
// {
//     int pipefd[N] = { 0 };
//     int n = pipe(pipefd);
//     if (n < 0) return 1;  //创建失败

//     // cout << "pipefd[0]:" << pipefd[0] << " " << ", pipefd[1]:" << pipefd[1] << endl;

//     //child->w, father->r;
//     pid_t id = fork();
//     if (id < 0) return 2;//创建子进程失败
//     else if (id == 0) //child
//     {  
//         //子进程写， 父进程读。 所以要关闭子进程的读入端， 关闭父进程的写入段。
//         close(pipefd[0]);

//         //IPCcode
//         Writer(pipefd[1]);

//         close(pipefd[1]);
//     }
//     //子进程写端完毕


//     //父进程关闭写入端
//     close(pipefd[1]);                           
//     Reader(pipefd[0]);

//     close(pipefd[0]);
//     cout << "father close read fd: " << pipefd[0] << endl;  //将读端打出来。

//     sleep(10);      
    

//     int status = 0;
//     //父进程要等待子进程
//     pid_t rid = waitpid(id, &status, 0); //父进程读取数据后，要等待子进程， 这里的退出码并不关心。 
//     if (rid < 0) return 3;
//     cout << "wait child success : " << rid << "exit code: " << ((status >> 8 )&0xFF) << "exit signal: " << (status&0x7F) << endl;

//     sleep(5);
//     cout << "father quit" << endl;
//     return 0;
// } 


#include<unistd.h>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<sys/types.h>
#include<sys/wait.h>
#include<cstring>

using namespace std;
#include<string> 

#define N 2
#define NUM 1024   //缓冲区最大大小

//child
void Writer(int wfd)
{
    string s = "hello, I am  child";
    pid_t self = getpid();  //获取自己的进程编号。 
    //写一些信息的时候， 带上编号
    int number = 0;
    
    //先定义缓冲区
    char buffer[NUM]; 
    while (true)
    {
        sleep(1);
        //构建发送字符串
        buffer[0] = 0; //字符串清空， 可以用来提醒阅读代码的人，这个是一个字符串
        //
        snprintf(buffer, sizeof(buffer), "%s-%d-%d", s.c_str(), self, number++);
        // cout << buffer << endl; //测试
        write(wfd, buffer, strlen(buffer));
    
    } 
}

//father
void Reader(int rfd)
{
    //创建buffer
    char buffer[NUM];
    int cnt = 0;
    while (true)
    {
        buffer[0] = 0; //告诉全世界， 这是个字符串
        ssize_t n = read(rfd, buffer, sizeof(buffer)); //sizeof !=  strlen, 这里不能strlen(buffer), 因为buffer里面没有\0.
        if(n > 0) //说明读取成功
        {
            buffer[n] = 0; //在最后一个字符的后面添加一个\0。   
            cout << "father: " << getpid() << ":" << buffer << endl;
        }
        else if (n == 0) break;
        else break;
        
        cnt++;
        if (cnt > 5) break;
    }
}



int main()
{
    int pipefd[N] = { 0 };
    int n = pipe(pipefd);
    if (n < 0) return 1;  //创建失败

    //child->w, father->r;
    pid_t id = fork();
    if (id < 0) return 2;//创建子进程失败
    else if (id == 0) //child
    {  
        //子进程写， 父进程读。 所以要关闭子进程的读入端， 关闭父进程的写入段。
        close(pipefd[0]);
        //IPCcode
        Writer(pipefd[1]);

        close(pipefd[1]);
    }
    //子进程写端完毕


    //父进程关闭写入端
    close(pipefd[1]);                           
    Reader(pipefd[0]);

    close(pipefd[0]);
    cout << "father close read fd: " << pipefd[0] << endl;  //将读端打出来。

    sleep(10);      

    int status = 0;
    //父进程要等待子进程
    pid_t rid = waitpid(id, &status, 0); //父进程读取数据后，要等待子进程， 这里的退出码并不关心。 
    if (rid < 0) return 3;
    cout << "wait child success : " << rid << "exit code: " << ((status >> 8 )&0xFF) << "exit signal: " << (status&0x7F) << endl;

    sleep(5);
    cout << "father quit" << endl;
    return 0;
} 
